package cn.duli.xianer.controller;

import cn.duli.xianer.pojo.*;
import cn.duli.xianer.service.GoodsService;
import cn.duli.xianer.service.OrdersService;
import cn.duli.xianer.service.ShopcarService;
import cn.duli.xianer.service.WantGoodsService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;


@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private ShopcarService shopcarService;

    @Autowired
    private WantGoodsService wantGoodsService;

    @Autowired
    private OrdersService ordersService;

    /**
     * 新增商品
     * @param goods
     * @return
     */
    @PostMapping("/save")
    @RequiresRoles("business")
    public MyResult save(Goods goods) {
        int gId = goodsService.save(goods);
        return new MyResult(200, "发布商品基本信息成功",null,null,gId,null);
    }
    /**
     * 修改商品
     * @param goods
     * @return
     */
    @RequestMapping("/update")
    @RequiresRoles("business")
    public MyResult update(Goods goods) {
        goodsService.update(goods);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("修改商品基本信息成功");
        return myResult;
    }

    /**
     * 根据id查找此商品基本信息
     * @param gId
     * @return
     */
    @GetMapping("/findById/{gId}")
    public MyResult findById(@PathVariable("gId") Integer gId){
        Goods good = goodsService.findById(gId);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setObject(good);
        myResult.setMsg("根据id查询商品基本信息成功");
        return myResult;
    }

    /**
     * 修改商品浏览量
     * @param goods
     * @return
     */
    @RequestMapping("/updateViewNum")
    public MyResult updateViewNum(Goods goods) {
        Goods good = goodsService.findById(goods.getgId());
        goods.setgViewNum(good.getgViewNum() + 1);
        goodsService.updateViewNum(goods);
        return new MyResult(200, "修改商品浏览量",null,null,null,null);
    }

    /**
     * 根据id删除商品信息（g_status=0）
     *
     * @param gId
     */
    @RequestMapping("/deleteById/{gId}")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult deleteById(@PathVariable("gId") Integer gId) {
        goodsService.deleteById(gId);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("根据id删除商品信息成功");
        return myResult;
    }

    /**
     * 根据id取消删除的商品(回收站回收某个商品)（g_status=1）
     *
     * @param gId
     */
    @RequestMapping("/cancelDeleteById/{gId}")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult cancelDeleteById(@PathVariable("gId") Integer gId) {
        goodsService.cancelDeleteById(gId);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("根据id取消删除的商品信息成功");
        return myResult;
    }


    /**
     * 根据id下架此商品（g_mode=0）
     *
     * @param gId
     */
    @RequestMapping("/shelveById/{gId}")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult shelveById(@PathVariable("gId") Integer gId) {
        goodsService.shelveById(gId);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("根据id下架此商品成功");
        return myResult;
    }


    /**
     * 根据id取消被下架的商品（上架）
     *
     * @param gId
     */
    @RequestMapping("/cancelShelveById/{gId}")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult cancelShelveById(@PathVariable("gId") Integer gId) {
        goodsService.cancelShelveById(gId);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("根据id取消被下架的商品成功");
        return myResult;
    }

    /**
     * 根据用户id查询该用户下架的商品列表
     * @param gUid
     * @return
     */
    @GetMapping("/findShelveByUserId")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult findShelveByUserId(@RequestParam("gUid") Integer gUid,
                                       @RequestParam(defaultValue = "1") int pageNo,
                                       @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findShelveByUserId(gUid));
        return new MyResult(200, "根据用户id查询该用户下架的商品列表成功",null,null,null,pageInfo);
    }

    /**
     * 根据用户id查询该用户审核中的商品列表
     * @param gUid
     * @return
     */
    @GetMapping("/findVerifyIngByUid")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult findVerifyIngByUid(@RequestParam("gUid") Integer gUid,
                                       @RequestParam(defaultValue = "1") int pageNo,
                                       @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findVerifyIngByUid(gUid));
        return new MyResult(200, "根据用户id查询该用户审核中的商品列表",null,null,null,pageInfo);
    }


    /**
     * 根据用户id查询该用户审核失败的商品列表
     * @param gUid
     * @return
     */
    @GetMapping("/findDieVerifyByUid")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business"})
    public MyResult findDieVerifyByUid(@RequestParam("gUid") Integer gUid,
                                       @RequestParam(defaultValue = "1") int pageNo,
                                       @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findDieVerifyByUid(gUid));
        return new MyResult(200, "根据用户id查询该用户审核失败的商品列表",null,null,null,pageInfo);
    }

    /**
     * 分页查询所有审核中的商品列表
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/findAllVerifyIng")
    @RequiresRoles("admin")
    public MyResult findAllVerifyIng(@RequestParam(defaultValue = "1") int pageNo,
                                   @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findAllVerifyIng());
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页查询所有审核中的商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页查询所有审核失败的商品列表
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/findDieVerify")
    @RequiresRoles("admin")
    public MyResult findDieVerify(@RequestParam(defaultValue = "1") int pageNo,
                                            @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findDieVerify());
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页查询所有审核失败的商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页查询所有正常售卖的商品列表
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/findSellIng")
    public MyResult findSellIng(@RequestParam(defaultValue = "1") int pageNo,
                                            @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findSellIng());
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页查询所有正常售卖的商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页查询所有下架了的商品列表
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/findShelved")
    @RequiresRoles("admin")
    public MyResult findShelved(@RequestParam(defaultValue = "1") int pageNo,
                                            @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findShelved());
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页查询所有下架了的商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 根据商品id修改此商品的审核状态
     * @param goods
     */
    @RequestMapping("/updateMode")
    @RequiresRoles("admin")
    public MyResult updateMode(Goods goods) {
        goodsService.updateMode(goods);
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("根据商品id修改此商品的审核状态成功");
        return myResult;
    }

    /**
     * 根据用户id查询此用户发布的商品列表
     * @param gUid
     * @return
     */
    @GetMapping("/findByUserId")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "business", "user"})
    public MyResult findByUserId(@RequestParam("gUid") Integer gUid,
                                 @RequestParam(defaultValue = "1") int pageNo,
                                 @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findByUserId(gUid));
        return new MyResult(200, "根据用户id查询此用户发布的商品列表",null,null,null,pageInfo);
    }

    /**
     * 分页查询所有商品
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/findAll")
    @RequiresRoles("admin")
    public MyResult findAll(@RequestParam(defaultValue = "1") int pageNo,
                               @RequestParam(defaultValue = "6") int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.findAll());
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页查询所有商品成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页根据商品名称模糊查询商品列表
     * @param gName
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryLikeByGoodName")
    public MyResult queryLikeByGoodName(@RequestParam(value="gName") String gName,
                                               @RequestParam(defaultValue = "1") int pageNo,
                                               @RequestParam(defaultValue = "6") int pageSize ) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.queryLikeByGoodName(gName));
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页根据商品名称模糊查询商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页根据类别名模糊查询商品列表
     * @param tName
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryLikeByTypeName")
    public MyResult queryLikeByTypeName(@RequestParam(value="tName") String tName,
                                               @RequestParam(defaultValue = "1") int pageNo,
                                               @RequestParam(defaultValue = "6") int pageSize ) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.queryLikeByTypeName(tName));
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页根据类别名模糊查询商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页根据发布地点查询商品列表
     * @param gAddr
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryLikeByAddr")
    public MyResult queryLikeByAddr(@RequestParam(value="gAddr") String gAddr,
                                               @RequestParam(defaultValue = "1") int pageNo,
                                               @RequestParam(defaultValue = "6") int pageSize ) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.queryLikeByAddr(gAddr));
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页根据发布地点查询商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页根据时间区间动态查询发布的商品列表
     * @param startTime
     * @param endTime
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryByTimeInterval")
    public MyResult queryByTimeInterval(String startTime,String endTime,
                                           @RequestParam(defaultValue = "1",required = false) int pageNo,
                                           @RequestParam(defaultValue = "6",required = false) int pageSize ){
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.queryByTimeInterval(startTime, endTime));
        MyResult myResult = new MyResult();
        myResult.setCode(200);
        myResult.setMsg("分页根据时间区间动态查询发布的商品列表成功");
        myResult.setPageInfo(pageInfo);
        return myResult;
    }

    /**
     * 分页根据二级类别id查询该类别下的商品列表
     * @param tId
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryByTypeTwoLevelId/{tId}")
    public MyResult queryByTypeTwoLevelId(@PathVariable("tId") Integer tId,
                                          @RequestParam(defaultValue = "1",required = false) int pageNo,
                                          @RequestParam(defaultValue = "6",required = false) int pageSize ) {
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.queryByTypeTwoLevelId(tId));
        return new MyResult(200, "分页根据二级类别id查询该类别下的商品列表成功",null,null,null,pageInfo);

    }

    /**
     * 根据时间区间、价格区间、商品成色、类别动态分页查询商品列表
     * @param startTime
     * @param endTime
     * @param lowPrice
     * @param topPrice
     * @param gLevel
     * @param gTid
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryDynamic")
    public MyResult queryDynamic(@RequestParam(defaultValue = "") String startTime,
                                 @RequestParam(defaultValue = "") String endTime,
                                 @RequestParam(defaultValue = "") String lowPrice,
                                 @RequestParam(defaultValue = "") String topPrice,
                                 @RequestParam(defaultValue = "") String gLevel,
                                 @RequestParam(defaultValue = "") String gTid,
                                @RequestParam(defaultValue = "1",required = false) int pageNo,
                                @RequestParam(defaultValue = "6",required = false) int pageSize){
        PageHelper.startPage(pageNo, pageSize);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsService.queryDynamic(startTime, endTime, lowPrice, topPrice, gLevel, gTid));
        return new MyResult(200, "动态分页查询商品列表成功",null,null,null,pageInfo);
    }

    /**
     * 查询商品表里面的所有成色
     * @return
     */
    @GetMapping("/findGlevel")
    public MyResult findGlevel() {
        List<Goods> goodsList = goodsService.findGlevel();
        return new MyResult(200, "查询商品表里面的所有成色",null,goodsList,null,null);
    }

    /**
     * 查询浏览量最多的前8条数据
     * @return
     */
    @GetMapping("/topByViewNum")
    public MyResult topByViewNum() {
        List<Goods> goodsList = goodsService.topByViewNum();
        return new MyResult(200, "查询浏览量最多的前8条数据",null,goodsList,null,null);
    }

    /**
     * 查询最新上架的前4条数据
     * @return
     */
    @GetMapping("/topNewTime")
    public MyResult topNewTime() {
        List<Goods> goodsList = goodsService.topNewTime();
        return new MyResult(200, "查询最新上架的前4条数据",null,goodsList,null,null);
    }

    /**
     * 根据用户id判断用户选中的商品是否还有库存（是否下架）
     * @param uId
     * @return 返回已经下架的商品列表，告知用户重新选购
     */
    @GetMapping(value = "/checkHas/{uId}")
    @RequiresRoles("business")
    public MyResult checkHas(@PathVariable("uId") Integer uId) {
        List<Shopcar> list = shopcarService.findGoodsByUserId(uId);
        List<Goods> goodsList = new ArrayList<>();
        for (int i=0;i<list.size();i++) {
            // 根据商品id查询该商品信息，判断模式是否为1
            Goods good = goodsService.findById(list.get(i).getsGid());
            if (good.getgMode()!=1) {
                goodsList.add(good);
            }
        }
        return new MyResult(200, "当前商品已下架",null,goodsList,null,null);
    }

    /**
     * 根据用户id查询此用户发布的所有商品列表
     * @param gUid
     * @return
     */
    @GetMapping("/findAllByUserId/{gUid}")
    @RequiresRoles("business")
    public MyResult findAllByUserId(@PathVariable("gUid") Integer gUid) {
        List<Goods> list = goodsService.findAllByUserId(gUid);
        return new MyResult(200, "根据用户id查询此用户发布的商品列表",null,list,null,null);
    }

    /**
     * 查找商品总数
     * @return
     */
    @RequestMapping("/findGoodsCount")
    @RequiresRoles("admin")
    public MyResult findGoodsCount() {
        int count = goodsService.findGoodsCount();
        return new MyResult(200, "查找商品总数成功",null,null,count,null);
    }

    /**
     * 查询总浏览数
     * @return
     */
    @RequestMapping("/findAllViewNum")
    @RequiresRoles("admin")
    public MyResult findAllViewNum() {
        int goodscount = 0;
        int wantGoodscount = 0;
        PageInfo<Goods> goodsPageInfo = new PageInfo<>(goodsService.findAll());
        for (int i=0;i<goodsPageInfo.getList().size();i++) {
            goodscount += goodsPageInfo.getList().get(i).getgViewNum();
        }
        PageInfo<WantGoods> wantGoodsPageInfo = new PageInfo<>(wantGoodsService.findAll());
        for (int i=0;i<wantGoodsPageInfo.getList().size();i++) {
            wantGoodscount += wantGoodsPageInfo.getList().get(i).getWgViewNum();
        }
        int count = goodscount + wantGoodscount;
        return new MyResult(200, "查找总浏览量成功",null,null,count,null);
    }


    /**
     * 查询购买商品成功后的推荐商品
     * @param uId
     * @param gId
     * @return
     */
    @GetMapping("/findRecommend")
    @RequiresRoles("business")
    public MyResult findRecommend(@RequestParam("uId") Integer uId,@RequestParam("gId") Integer gId) {
        // (当前登录用户id为uId)
        // 根据当前登录用户id查找此用户购买的订单商品列表
        List<Orders> ordersList = ordersService.findByCurrentUid(uId);// 查商品ids
        List<Integer> current = new LinkedList<>();  // 当前商品ids
        Set<Integer> other = new HashSet<>();  // 其他商品ids
        List<Integer> mixed = new LinkedList<>();  // 交集
        List<Integer> all = new LinkedList<>();  // 并集
        Set<Integer> end = new HashSet<>(); // 满足相似度条件的数据列表
        List<Goods> thisList = new ArrayList<>();  // 新推荐数据
        for (int i=0;i<ordersList.size();i++) {
            current.add(ordersList.get(i).getoGid());
            // 根据商品id查询关于此商品的订单列表【获取用户ids（排除当前登录用户的商品订单列表）】
            List<Orders> ordersList1 =
                    ordersService.findOrdersByGid(ordersList.get(i).getoGid(),ordersList.get(i).getoUid());
            // 查询购买此商品的用户所购买的商品列表
            for (int j=0;j<ordersList1.size();j++) {
                List<Orders> ordersList2 = ordersService.findByOthersUid(ordersList1.get(j).getoUid());// 根据用户ids查询商品ids
                for(Orders orders:ordersList2){
                    other.add(orders.getoGid());
                }
                mixed.clear();
                mixed.addAll(current);
                mixed.retainAll(other);  // 交集
                System.out.println("交集：" + mixed);
                Integer temp1 = mixed.size();
                all.clear();
                all.addAll(current);  // 并集
                all.removeAll(other);  // 差集
                all.addAll(other);
                System.out.println("并集：" + all);
                Integer temp2 = all.size();
                float similarity = (float)(Math.round(((float)temp1/temp2)*100))/100;  // 相似度(四舍五入保留两位小数)
                System.out.println("相似度:" + similarity);
                System.out.println("current:" + current);
                System.out.println("other:" + other);
                System.out.println("mixed:" + mixed);
                // 如果相似度在0.3-1之间，放入set集合中
                if (similarity>=0.3) {
                    for (Integer m:other) {
                        for (Integer n:mixed) {
                            if (!m.equals(n)) {
                                end.add(m);
                            }
                        }
                    }
                    // 判断end的长度是否大于3.大于3，取前3个推荐
                    // 小于3的话，先查询set中的元素，再查询(3-end的长度)个元素 - 前提：元素不能存在于end中；不能是用户当前购买的商品
                    if (end.size()>=3) {
                        List<Integer> list = new LinkedList<>(end); // Set转list
                        for (int k=0;k<list.size();k++) {
                            if (k<3) {
                                // 查找商品，放入list集合中
                                Goods good = goodsService.findById(list.get(k));
                                thisList.add(good);
                                System.out.println("thisList1:" + thisList);
                            }
                        }
                    } else {
                        List<Goods> list = goodsService.findByIds(end);
                        thisList = goodsService.findRecommend(end, gId, 3-end.size());
                        thisList.addAll(list);
                    }
                } else {
                    // 随机推荐3个
                    thisList = goodsService.findRecommend(end, gId, 3-end.size());
                }
            }
            if (mixed.size()==0&&all.size()==0) {
                // 随机推荐3个
                thisList = goodsService.findRecommend(end, gId, 3-end.size());
            }
        }
        return new MyResult(200, "查询购买商品成功后的推荐商品",null,thisList,null,null);
    }


    /**
     * 根据时间区间动态查询发布的商品列表
     * @param startTime
     * @param endTime
     * @return
     */
    @GetMapping("/queryByTimeIntervalTwo")
    public MyResult queryByTimeIntervalTwo(String startTime,String endTime){
        List<Goods> list = goodsService.queryByTimeIntervalTwo(startTime, endTime);
        return new MyResult(200, "根据时间区间动态查询发布的商品列表",null,list,null,null);
    }

}
